home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows (5th Edition) / Programming Windows, 5th ed. - Companion CD (097-0002183)(1999).iso / Chap16 / Dibble / DibPal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-09  |  18.2 KB  |  596 lines

  1. /*----------------------------------------
  2.    DIBPAL.C -- Palette-Creation Functions
  3.                (c) Charles Petzold, 1998
  4.   ----------------------------------------*/
  5.  
  6. #include <windows.h>
  7. #include "dibhelp.h"
  8. #include "dibpal.h"
  9.  
  10. /*------------------------------------------------------------
  11.    DibPalDibTable: Creates a palette from the DIB color table
  12.   ------------------------------------------------------------*/
  13.  
  14. HPALETTE DibPalDibTable (HDIB hdib)
  15. {
  16.      HPALETTE     hPalette ;
  17.      int          i, iNum ;
  18.      LOGPALETTE * plp ;
  19.      RGBQUAD      rgb ;
  20.  
  21.      if (0 == (iNum = DibNumColors (hdib)))
  22.           return NULL ;
  23.  
  24.      plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
  25.  
  26.      plp->palVersion    = 0x0300 ;
  27.      plp->palNumEntries = iNum ;
  28.  
  29.      for (i = 0 ; i < iNum ; i++)
  30.      {
  31.           DibGetColor (hdib, i, &rgb) ;
  32.  
  33.           plp->palPalEntry[i].peRed   = rgb.rgbRed ;
  34.           plp->palPalEntry[i].peGreen = rgb.rgbGreen ;
  35.           plp->palPalEntry[i].peBlue  = rgb.rgbBlue ;
  36.           plp->palPalEntry[i].peFlags = 0 ;
  37.      }
  38.      hPalette = CreatePalette (plp) ;
  39.      free (plp) ;
  40.      return hPalette ;
  41. }
  42.  
  43. /*------------------------------------------------------------------------
  44.    DibPalAllPurpose: Creates a palette suitable for a wide variety
  45.           of images; the palette has 247 entries, but 15 of them are 
  46.           duplicates or match the standard 20 colors.
  47.   ------------------------------------------------------------------------*/
  48.  
  49. HPALETTE DibPalAllPurpose (void)
  50. {
  51.      HPALETTE     hPalette ;
  52.      int          i, incr, R, G, B ;
  53.      LOGPALETTE * plp ;
  54.  
  55.      plp = malloc (sizeof (LOGPALETTE) + 246 * sizeof (PALETTEENTRY)) ;
  56.  
  57.      plp->palVersion    = 0x0300 ;
  58.      plp->palNumEntries = 247 ;
  59.  
  60.           // The following loop calculates 31 grays shades, but 3 of them
  61.           //        will match the standard 20 colors
  62.  
  63.      for (i = 0, G = 0, incr = 8 ; G <= 0xFF ; i++, G += incr)
  64.      {
  65.           plp->palPalEntry[i].peRed   = (BYTE) G ;
  66.           plp->palPalEntry[i].peGreen = (BYTE) G ;
  67.           plp->palPalEntry[i].peBlue  = (BYTE) G ;
  68.           plp->palPalEntry[i].peFlags = 0 ;
  69.  
  70.           incr = (incr == 9 ? 8 : 9) ;
  71.      }
  72.  
  73.           // The following loop is responsible for 216 entries, but 8 of 
  74.           //        them will match the standard 20 colors, and another
  75.           //        4 of them will match the gray shades above.
  76.  
  77.      for (R = 0 ; R <= 0xFF ; R += 0x33)
  78.      for (G = 0 ; G <= 0xFF ; G += 0x33)
  79.      for (B = 0 ; B <= 0xFF ; B += 0x33)
  80.      {
  81.           plp->palPalEntry[i].peRed   = (BYTE) R ;
  82.           plp->palPalEntry[i].peGreen = (BYTE) G ;
  83.           plp->palPalEntry[i].peBlue  = (BYTE) B ;
  84.           plp->palPalEntry[i].peFlags = 0 ;
  85.  
  86.           i++ ;
  87.      }
  88.      hPalette = CreatePalette (plp) ;
  89.  
  90.      free (plp) ;
  91.      return hPalette ;
  92. }
  93.  
  94. /*------------------------------------------------------------------------
  95.    DibPalUniformGrays:  Creates a palette of iNum grays, uniformly spaced
  96.   ------------------------------------------------------------------------*/
  97.  
  98. HPALETTE DibPalUniformGrays (int iNum)
  99. {
  100.      HPALETTE     hPalette ;
  101.      int          i ;
  102.      LOGPALETTE * plp ;
  103.  
  104.      plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
  105.  
  106.      plp->palVersion    = 0x0300 ;
  107.      plp->palNumEntries = iNum ;
  108.  
  109.      for (i = 0 ; i < iNum ; i++)
  110.      {
  111.           plp->palPalEntry[i].peRed   =
  112.           plp->palPalEntry[i].peGreen = 
  113.           plp->palPalEntry[i].peBlue  = (BYTE) (i * 255 / (iNum - 1)) ;
  114.           plp->palPalEntry[i].peFlags = 0 ;
  115.      }
  116.      hPalette = CreatePalette (plp) ;
  117.      free (plp) ;
  118.      return hPalette ;
  119. }
  120.  
  121. /*------------------------------------------------------------------------
  122.    DibPalUniformColors: Creates a palette of iNumR x iNumG x iNumB colors
  123.   ------------------------------------------------------------------------*/
  124.  
  125. HPALETTE DibPalUniformColors (int iNumR, int iNumG, int iNumB)
  126. {
  127.      HPALETTE     hPalette ;
  128.      int          i, iNum, R, G, B ;
  129.      LOGPALETTE * plp ;
  130.  
  131.      iNum = iNumR * iNumG * iNumB ;
  132.  
  133.      plp = malloc (sizeof (LOGPALETTE) + (iNum - 1) * sizeof (PALETTEENTRY)) ;
  134.  
  135.      plp->palVersion    = 0x0300 ;
  136.      plp->palNumEntries = iNumR * iNumG * iNumB ;
  137.  
  138.      i = 0 ;
  139.      for (R = 0 ; R < iNumR ; R++)
  140.      for (G = 0 ; G < iNumG ; G++)
  141.      for (B = 0 ; B < iNumB ; B++)
  142.      {
  143.           plp->palPalEntry[i].peRed   = (BYTE) (R * 255 / (iNumR - 1)) ;
  144.           plp->palPalEntry[i].peGreen = (BYTE) (G * 255 / (iNumG - 1)) ;
  145.           plp->palPalEntry[i].peBlue  = (BYTE) (B * 255 / (iNumB - 1)) ;
  146.           plp->palPalEntry[i].peFlags = 0 ;
  147.  
  148.           i++ ;
  149.      }
  150.      hPalette = CreatePalette (plp) ;
  151.      free (plp) ;
  152.      return hPalette ;
  153. }
  154.  
  155. /*---------------------------------------------------------------
  156.    DibPalVga:  Creates a palette based on standard 16 VGA colors
  157.   ---------------------------------------------------------------*/
  158.  
  159. HPALETTE DibPalVga (void)
  160. {
  161.      static RGBQUAD rgb [16] = { 0x00, 0x00, 0x00, 0x00,
  162.                                  0x00, 0x00, 0x80, 0x00,
  163.                                  0x00, 0x80, 0x00, 0x00,
  164.                                  0x00, 0x80, 0x80, 0x00,
  165.                                  0x80, 0x00, 0x00, 0x00,
  166.                                  0x80, 0x00, 0x80, 0x00,
  167.                                  0x80, 0x80, 0x00, 0x00,
  168.                                  0x80, 0x80, 0x80, 0x00,
  169.                                  0xC0, 0xC0, 0xC0, 0x00,
  170.                                  0x00, 0x00, 0xFF, 0x00,
  171.                                  0x00, 0xFF, 0x00, 0x00,
  172.                                  0x00, 0xFF, 0xFF, 0x00,
  173.                                  0xFF, 0x00, 0x00, 0x00,
  174.                                  0xFF, 0x00, 0xFF, 0x00,
  175.                                  0xFF, 0xFF, 0x00, 0x00,
  176.                                  0xFF, 0xFF, 0xFF, 0x00 } ;
  177.      HPALETTE       hPalette ;
  178.      int            i ;
  179.      LOGPALETTE   * plp ;
  180.  
  181.      plp = malloc (sizeof (LOGPALETTE) + 15 * sizeof (PALETTEENTRY)) ;
  182.  
  183.      plp->palVersion    = 0x0300 ;
  184.      plp->palNumEntries = 16 ;
  185.  
  186.      for (i = 0 ; i < 16 ; i++)
  187.      {
  188.           plp->palPalEntry[i].peRed   = rgb[i].rgbRed ;
  189.           plp->palPalEntry[i].peGreen = rgb[i].rgbGreen ;
  190.           plp->palPalEntry[i].peBlue  = rgb[i].rgbBlue ;
  191.           plp->palPalEntry[i].peFlags = 0 ;
  192.      }
  193.      hPalette = CreatePalette (plp) ;
  194.      free (plp) ;
  195.      return hPalette ;
  196. }
  197.  
  198. /*---------------------------------------------
  199.    Macro used in palette optimization routines
  200.   ---------------------------------------------*/
  201.  
  202. #define PACK_RGB(R,G,B,iRes) ((int) (R) | ((int) (G) <<  (iRes)) |       \
  203.                                           ((int) (B) << ((iRes) + (iRes))))
  204.  
  205. /*--------------------------------------------------------------------
  206.    AccumColorCounts: Fills up piCount (indexed by a packed RGB color)
  207.      with counts of pixels of that color.
  208.   --------------------------------------------------------------------*/
  209.  
  210. static void AccumColorCounts (HDIB hdib, int * piCount, int iRes)
  211. {
  212.      int     x, y, cx, cy ;
  213.      RGBQUAD rgb ;
  214.  
  215.      cx = DibWidth (hdib) ;
  216.      cy = DibHeight (hdib) ;
  217.  
  218.      for (y = 0 ; y < cy ; y++)
  219.      for (x = 0 ; x < cx ; x++)
  220.      {
  221.           DibGetPixelColor (hdib, x, y, &rgb) ;
  222.  
  223.           rgb.rgbRed   >>= (8 - iRes) ;
  224.           rgb.rgbGreen >>= (8 - iRes) ;
  225.           rgb.rgbBlue  >>= (8 - iRes) ;
  226.  
  227.           ++piCount [PACK_RGB (rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue, iRes)] ;
  228.      }
  229. }
  230.  
  231. /*--------------------------------------------------------------
  232.    DibPalPopularity:  Popularity algorithm for optimized colors
  233.   --------------------------------------------------------------*/
  234.  
  235. HPALETTE DibPalPopularity (HDIB hdib, int iRes)
  236. {
  237.      HPALETTE     hPalette ;
  238.      int          i, iArraySize, iEntry, iCount, iIndex, iMask, R, G, B ;
  239.      int        * piCount ;
  240.      LOGPALETTE * plp ;
  241.  
  242.           // Validity checks
  243.     
  244.      if (DibBitCount (hdib) < 16)
  245.           return NULL ;
  246.  
  247.      if (iRes < 3 || iRes > 8)
  248.           return NULL ;
  249.  
  250.           // Allocate array for counting pixel colors
  251.  
  252.      iArraySize = 1 << (3 * iRes) ;
  253.      iMask = (1 << iRes) - 1 ;
  254.  
  255.      if (NULL == (piCount = calloc (iArraySize, sizeof (int))))
  256.           return NULL ;
  257.  
  258.           // Get the color counts
  259.  
  260.      AccumColorCounts (hdib, piCount, iRes) ;
  261.  
  262.           // Set up a palette
  263.  
  264.      plp = malloc (sizeof (LOGPALETTE) + 235 * sizeof (PALETTEENTRY)) ;
  265.  
  266.      plp->palVersion = 0x0300 ;
  267.  
  268.      for (iEntry = 0 ; iEntry < 236 ; iEntry++)
  269.      {
  270.           for (i = 0, iCount = 0 ; i < iArraySize ; i++)
  271.                if (piCount[i] > iCount)
  272.                {
  273.                     iCount = piCount[i] ;
  274.                     iIndex = i ;
  275.                }
  276.  
  277.           if (iCount == 0)
  278.                break ;
  279.  
  280.           R = (iMask &  iIndex                  ) << (8 - iRes) ;
  281.           G = (iMask & (iIndex >>         iRes )) << (8 - iRes) ;
  282.           B = (iMask & (iIndex >> (iRes + iRes))) << (8 - iRes) ;
  283.  
  284.           plp->palPalEntry[iEntry].peRed   = (BYTE) R ; 
  285.           plp->palPalEntry[iEntry].peGreen = (BYTE) G ; 
  286.           plp->palPalEntry[iEntry].peBlue  = (BYTE) B ; 
  287.           plp->palPalEntry[iEntry].peFlags = 0 ;
  288.  
  289.           piCount [iIndex] = 0 ;
  290.      }
  291.           // On exit from the loop iEntry will be the number of stored entries
  292.  
  293.      plp->palNumEntries = iEntry ;
  294.  
  295.           // Create the palette, clean up, and return the palette handle
  296.  
  297.      hPalette = CreatePalette (plp) ;
  298.  
  299.      free (piCount) ;
  300.      free (plp) ;
  301.  
  302.      return hPalette ;
  303. }
  304.  
  305. /*-------------------------------------------------------
  306.    Structures used for implementing median cut algorithm
  307.   -------------------------------------------------------*/
  308.  
  309. typedef struct           // defines dimension of a box
  310. {
  311.      int Rmin, Rmax, Gmin, Gmax, Bmin, Bmax ;
  312. }
  313. MINMAX ;
  314.  
  315. typedef struct           // for Compare routine for qsort
  316. {
  317.      int     iBoxCount ;
  318.      RGBQUAD rgbBoxAv ;
  319. }
  320. BOXES ;
  321.  
  322. /*----------------------------
  323.    FindAverageColor: In a box
  324.   ----------------------------*/
  325.  
  326. static int FindAverageColor (int * piCount, MINMAX mm, 
  327.                              int iRes, RGBQUAD * prgb)
  328. {
  329.      int R, G, B, iR, iG, iB, iTotal, iCount ;
  330.  
  331.           // Initialize some variables
  332.  
  333.      iTotal = iR = iG = iB = 0 ;
  334.           
  335.           // Loop through all colors in the box
  336.           
  337.      for (R = mm.Rmin ; R <= mm.Rmax ; R++)
  338.      for (G = mm.Gmin ; G <= mm.Gmax ; G++)
  339.      for (B = mm.Bmin ; B <= mm.Bmax ; B++)
  340.      {
  341.                // Get the number of pixels of that color
  342.  
  343.           iCount = piCount [PACK_RGB (R, G, B, iRes)] ;
  344.  
  345.                // Weight the pixel count by the color value
  346.  
  347.           iR += iCount * R ;
  348.           iG += iCount * G ;
  349.           iB += iCount * B ;
  350.  
  351.           iTotal += iCount ;
  352.      }
  353.           // Find the average color
  354.  
  355.      prgb->rgbRed   = (BYTE) ((iR / iTotal) << (8 - iRes)) ;
  356.      prgb->rgbGreen = (BYTE) ((iG / iTotal) << (8 - iRes)) ;
  357.      prgb->rgbBlue  = (BYTE) ((iB / iTotal) << (8 - iRes)) ;
  358.  
  359.           // Return the total number of pixels in the box
  360.      
  361.      return iTotal ;
  362. }
  363.  
  364. /*------------------------------
  365.    CutBox:  Divide a box in two
  366.   ------------------------------*/
  367.  
  368. static void CutBox (int * piCount, int iBoxCount, MINMAX mm,
  369.                     int iRes, int iLevel, BOXES * pboxes, int * piEntry)
  370. {
  371.      int    iCount, R, G, B ;
  372.      MINMAX mmNew ;
  373.      
  374.           // If the box is empty, return 
  375.  
  376.      if (iBoxCount == 0)
  377.           return ;
  378.  
  379.           // If the nesting level is 8, or the box is one pixel, we're ready
  380.           //   to find the average color in the box and save it along with
  381.           //   the number of pixels of that color
  382.  
  383.      if (iLevel == 8 || (mm.Rmin == mm.Rmax && 
  384.                          mm.Gmin == mm.Gmax && 
  385.                          mm.Bmin == mm.Bmax))
  386.      {
  387.           pboxes[*piEntry].iBoxCount = 
  388.                FindAverageColor (piCount, mm, iRes, &pboxes[*piEntry].rgbBoxAv) ;
  389.  
  390.           (*piEntry) ++ ;
  391.      }
  392.           // Otherwise, if blue is the largest side, split it
  393.  
  394.      else if ((mm.Bmax - mm.Bmin > mm.Rmax - mm.Rmin) && 
  395.               (mm.Bmax - mm.Bmin > mm.Gmax - mm.Gmin))
  396.      {
  397.                // Initialize a counter and loop through the blue side
  398.  
  399.           iCount = 0 ;
  400.  
  401.           for (B = mm.Bmin ; B < mm.Bmax ; B++)
  402.           {
  403.                     // Accumulate all the pixels for each successive blue value
  404.  
  405.                for (R = mm.Rmin ; R <= mm.Rmax ; R++)
  406.                for (G = mm.Gmin ; G <= mm.Gmax ; G++)
  407.                     iCount += piCount [PACK_RGB (R, G, B, iRes)] ;
  408.  
  409.                     // If it's more than half the box count, we're there
  410.  
  411.                if (iCount >= iBoxCount / 2)
  412.                     break ;
  413.  
  414.                     // If the next blue value will be the max, we're there
  415.  
  416.                if (B == mm.Bmax - 1)
  417.                     break ;
  418.           }
  419.                // Cut the two split boxes.
  420.                //   The second argument to CutBox is the new box count.
  421.                //   The third argument is the new min and max values.
  422.  
  423.           mmNew = mm ;
  424.           mmNew.Bmin = mm.Bmin ;
  425.           mmNew.Bmax = B ;
  426.  
  427.           CutBox (piCount, iCount, mmNew, iRes, iLevel + 1, 
  428.                   pboxes, piEntry) ;
  429.  
  430.           mmNew.Bmin = B + 1 ;
  431.           mmNew.Bmax = mm.Bmax ;
  432.  
  433.           CutBox (piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
  434.                   pboxes, piEntry) ;
  435.      }
  436.           // Otherwise, if red is the largest side, split it (just like blue)
  437.  
  438.      else if (mm.Rmax - mm.Rmin > mm.Gmax - mm.Gmin)
  439.      {
  440.           iCount = 0 ;
  441.  
  442.           for (R = mm.Rmin ; R < mm.Rmax ; R++)
  443.           {
  444.                for (B = mm.Bmin ; B <= mm.Bmax ; B++)
  445.                for (G = mm.Gmin ; G <= mm.Gmax ; G++)
  446.                     iCount += piCount [PACK_RGB (R, G, B, iRes)] ;
  447.  
  448.                if (iCount >= iBoxCount / 2)
  449.                     break ;
  450.  
  451.                if (R == mm.Rmax - 1)
  452.                     break ;
  453.           }
  454.           mmNew = mm ;
  455.           mmNew.Rmin = mm.Rmin ;
  456.           mmNew.Rmax = R ;
  457.  
  458.           CutBox (piCount, iCount, mmNew, iRes, iLevel + 1, 
  459.                   pboxes, piEntry) ;
  460.  
  461.           mmNew.Rmin = R + 1 ;
  462.           mmNew.Rmax = mm.Rmax ;
  463.  
  464.           CutBox (piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
  465.                   pboxes, piEntry) ;
  466.      }
  467.           // Otherwise, split along the green size
  468.      else 
  469.      {
  470.           iCount = 0 ;
  471.  
  472.           for (G = mm.Gmin ; G < mm.Gmax ; G++)
  473.           {
  474.                for (B = mm.Bmin ; B <= mm.Bmax ; B++)
  475.                for (R = mm.Rmin ; R <= mm.Rmax ; R++)
  476.                     iCount += piCount [PACK_RGB (R, G, B, iRes)] ;
  477.  
  478.                if (iCount >= iBoxCount / 2)
  479.                     break ;
  480.  
  481.                if (G == mm.Gmax - 1)
  482.                     break ;
  483.           }
  484.           mmNew = mm ;
  485.           mmNew.Gmin = mm.Gmin ;
  486.           mmNew.Gmax = G ;
  487.  
  488.           CutBox (piCount, iCount, mmNew, iRes, iLevel + 1, 
  489.                   pboxes, piEntry) ;
  490.  
  491.           mmNew.Gmin = G + 1 ;
  492.           mmNew.Gmax = mm.Gmax ;
  493.  
  494.           CutBox (piCount, iBoxCount - iCount, mmNew, iRes, iLevel + 1,
  495.                   pboxes, piEntry) ;
  496.      }
  497. }
  498.  
  499. /*---------------------------
  500.    Compare routine for qsort
  501.   ---------------------------*/
  502.  
  503. static int Compare (const BOXES * pbox1, const BOXES * pbox2)
  504. {
  505.      return pbox1->iBoxCount - pbox2->iBoxCount ;
  506. }
  507.  
  508. /*-----------------------------------------------------------------
  509.    DibPalMedianCut:  Creates palette based on median cut algorithm
  510.   -----------------------------------------------------------------*/
  511.  
  512. HPALETTE DibPalMedianCut (HDIB hdib, int iRes)
  513. {
  514.      BOXES        boxes [256] ;
  515.      HPALETTE     hPalette ;
  516.      int          i, iArraySize, iCount, R, G, B, iTotCount, iDim, iEntry = 0 ;
  517.      int        * piCount ;
  518.      LOGPALETTE * plp ;
  519.      MINMAX       mm ;
  520.  
  521.           // Validity checks
  522.     
  523.      if (DibBitCount (hdib) < 16)
  524.           return NULL ;
  525.  
  526.      if (iRes < 3 || iRes > 8)
  527.           return NULL ;
  528.  
  529.           // Accumulate counts of pixel colors
  530.  
  531.      iArraySize = 1 << (3 * iRes) ;
  532.  
  533.      if (NULL == (piCount = calloc (iArraySize, sizeof (int))))
  534.           return NULL ;
  535.  
  536.      AccumColorCounts (hdib, piCount, iRes) ;
  537.  
  538.           // Find the dimensions of the total box
  539.  
  540.      iDim = 1 << iRes ;
  541.  
  542.      mm.Rmin = mm.Gmin = mm.Bmin = iDim - 1 ;
  543.      mm.Rmax = mm.Gmax = mm.Bmax = 0 ;
  544.  
  545.      iTotCount = 0 ;
  546.  
  547.      for (R = 0 ; R < iDim ; R++)
  548.      for (G = 0 ; G < iDim ; G++)
  549.      for (B = 0 ; B < iDim ; B++)
  550.           if ((iCount = piCount [PACK_RGB (R, G, B, iRes)]) > 0)
  551.           {
  552.                iTotCount += iCount ;
  553.  
  554.                if (R < mm.Rmin) mm.Rmin = R ;
  555.                if (G < mm.Gmin) mm.Gmin = G ;
  556.                if (B < mm.Bmin) mm.Bmin = B ;
  557.  
  558.                if (R > mm.Rmax) mm.Rmax = R ;
  559.                if (G > mm.Gmax) mm.Gmax = G ;
  560.                if (B > mm.Bmax) mm.Bmax = B ;
  561.           }
  562.  
  563.           // Cut the first box (iterative function).
  564.           //   On return, the boxes structure will have up to 256 RGB values, 
  565.           //        one for each of the boxes, and the number of pixels in
  566.           //        each box.
  567.           //   The iEntry value will indicate the number of non-empty boxes.
  568.  
  569.      CutBox (piCount, iTotCount, mm, iRes, 0, boxes, &iEntry) ;
  570.      free (piCount) ;
  571.  
  572.           // Sort the RGB table by the number of pixels for each color
  573.  
  574.      qsort (boxes, iEntry, sizeof (BOXES), Compare) ;
  575.  
  576.      plp = malloc (sizeof (LOGPALETTE) + (iEntry - 1) * sizeof (PALETTEENTRY)) ;
  577.  
  578.      if (plp == NULL)
  579.           return NULL ;
  580.  
  581.      plp->palVersion    = 0x0300 ;
  582.      plp->palNumEntries = iEntry ;
  583.  
  584.      for (i = 0 ; i < iEntry ; i++)
  585.      {
  586.           plp->palPalEntry[i].peRed   = boxes[i].rgbBoxAv.rgbRed ;
  587.           plp->palPalEntry[i].peGreen = boxes[i].rgbBoxAv.rgbGreen ;
  588.           plp->palPalEntry[i].peBlue  = boxes[i].rgbBoxAv.rgbBlue ;
  589.           plp->palPalEntry[i].peFlags = 0 ;
  590.      }
  591.  
  592.      hPalette = CreatePalette (plp) ;
  593.  
  594.      free (plp) ;
  595.      return hPalette ;
  596. }